package main

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"
	"net/http/cookiejar"
	"os"
	"strings"
	"time"

	"github.com/opesun/goquery"
)

func GetStatistics() {
	initAll()
	//获得省
	provUrl := url + "index.html"
	provinces := GetProv("root", provUrl)
	Println("省", len(provinces))
	WriteFile(provinces, provUrl)
	for _, prov := range provinces {
		//prov = provinces[2] //设置指定省
		provName := prov.Name
		//获得市
		cityUrl := FUrl(provUrl) + prov.Href
		citys := GetCity(prov.Code, cityUrl)
		Println(provName, "\t", len(citys), "市")
		WriteFile(citys, cityUrl)
		for _, city := range citys {
			//获得县
			countUrl := FUrl(cityUrl) + city.Href
			countys := GetCounty(city.Code, countUrl)
			Println(provName, city.Name, "\t\t", len(countys), "县")
			WriteFile(countys, countUrl)
			for _, county := range countys {
				//获得街道、镇
				townUrl := FUrl(countUrl) + county.Href
				towns := GetTown(county.Code, townUrl)
				Println(provName, city.Name, county.Name, "\t\t\t", len(towns), "街道、镇")
				WriteFile(towns, townUrl)
				for _, town := range towns {
					//获得村
					villageUrl := FUrl(townUrl) + town.Href
					villages := GetVillage(town.Code, villageUrl)
					Println(provName, city.Name, county.Name, town.Name, "\t\t\t\t", len(villages), "村")
					WriteFile(villages, villageUrl)
					//break
				}
				Println(provName, city.Name, county.Name, "end")
				//break
			}
			Println(provName, city.Name, "end")
			//break
		}
		Println(provName, "end")
		//break
	}
	Println("省", "end")
}

//输出文件
func WriteFile(data interface{}, url string) {
	var l int
	switch d := data.(type) {
	case []Province:
		l = len(d)
		break
	case []City:
		l = len(d)
		break
	case []County:
		l = len(d)
		break
	case []Town:
		l = len(d)
		break
	case []Village:
		l = len(d)
		break
	}
	if l == 0 {
		errLogger.Println(url)
	} else {
		byteJsn, _ := json.Marshal(data)
		succFile.Write(byteJsn)
		succFile.Write([]byte("\r\n"))
	}
}

//获得村
func GetVillage(pcode, url string) []Village {
	out := HttpGet(url)
	n, err := goquery.ParseString(string(out))
	if err != nil {
		Println(err)
	}
	n = n.Find(".villagetable")
	n = n.Find(".villagetr")
	villages := make([]Village, 0, n.Length())
	for i := 0; i < n.Length(); i++ {
		tr := n.Eq(i)
		tds := tr.Find("td")
		td0 := tds.Eq(0)
		td1 := tds.Eq(1)
		td2 := tds.Eq(2)
		code := td0.Text()
		name := td2.Text()
		if IsNameNull(name, code) {
			return GetVillage(pcode, url)
		}
		village := Village{Pcode: pcode, Code: code, Classify: td1.Text(), Name: name}
		villages = append(villages, village)
	}
	return villages

}

//获得县下的街道、镇
func GetTown(pcode, url string) []Town {
	out := HttpGet(url)
	n, err := goquery.ParseString(string(out))
	if err != nil {
		Println(err)
	}
	n = n.Find(".towntable")
	n = n.Find(".towntr")
	towns := make([]Town, 0, n.Length())
	for i := 0; i < n.Length(); i++ {
		tr := n.Eq(i)
		tds := tr.Find("td")
		td0 := tds.Eq(0)
		td1 := tds.Eq(1)
		href := td0.Find("a").Attr("href")
		code := td0.Text()
		name := td1.Text()
		if IsNameNull(name, code) {
			return GetTown(pcode, url)
		}
		town := Town{Pcode: pcode, Name: name, Href: href, Code: code}
		towns = append(towns, town)
	}
	return towns
}

//获得县
func GetCounty(pcode, url string) []County {
	out := HttpGet(url)
	n, err := goquery.ParseString(string(out))
	if err != nil {
		Println(err)
	}
	n = n.Find(".countytable")
	n = n.Find(".countytr")
	countys := make([]County, 0, n.Length())
	for i := 0; i < n.Length(); i++ {
		tr := n.Eq(i)
		tds := tr.Find("td")
		td0 := tds.Eq(0)
		td1 := tds.Eq(1)
		href := td0.Find("a").Attr("href")
		code := td0.Text()
		name := td1.Text()
		if IsNameNull(name, code) {
			return GetCounty(pcode, url)
		}
		county := County{Pcode: pcode, Name: name, Href: href, Code: code}
		countys = append(countys, county)
	}
	return countys
}

//获得市
func GetCity(pcode, url string) []City {
	out := HttpGet(url)
	n, err := goquery.ParseString(string(out))
	if err != nil {
		Println(err)
	}
	n = n.Find(".citytable")
	n = n.Find(".citytr")
	citys := make([]City, 0, n.Length())
	for i := 0; i < n.Length(); i++ {
		tr := n.Eq(i)
		tds := tr.Find("td")
		td0 := tds.Eq(0)
		td1 := tds.Eq(1)
		href := td0.Find("a").Attr("href")
		code := td0.Text()
		name := td1.Text()
		if IsNameNull(name, code) {
			return GetCity(pcode, url)
		}
		city := City{Pcode: pcode, Name: name, Href: href, Code: code}
		citys = append(citys, city)
	}
	return citys
}

//获得省
func GetProv(pcode, url string) []Province {
	out := HttpGet(url)
	n, err := goquery.ParseString(string(out))
	if err != nil {
		Println(err)
	}
	n = n.Find(".provincetable")
	len := n.Find(".provincetr").Length()
	provinces := make([]Province, 0, 30)
	for i := 0; i < len; i++ {
		tr := n.Eq(i)
		as := tr.Find("a")
		alen := as.Length()
		for j := 0; j < alen; j++ {
			a := as.Eq(j)
			href := a.Attr("href")
			name := a.Text()
			code := strings.Split(href, ".")[0] + "0000000000"
			province := Province{Pcode: pcode, Name: name, Href: href, Code: code}
			provinces = append(provinces, province)
		}
	}
	return provinces
}

func IsNameNull(name, code string) bool {
	if name == "" || code == "" {
		Println("name=", name, "code=", code)
		time.Sleep(time.Second)
		return true
	}
	return false
}

func HttpGet(url string) []byte {
	return HttpGetI(url, 0)
}

func HttpGetI(url string, i int) []byte {
	time.Sleep(time.Second / 2)
	var out []byte
	if i > 5 {
		return out
	}
	client := &http.Client{
		Jar:     gCurCookieJar,
		Timeout: time.Duration(30 * time.Second), //设置超时 单位秒
	}
	Println("Request Url：", url)
	req, err := http.NewRequest("GET", url, nil)
	if err != nil {
		Println("重试", err, i+1)
		return HttpGetI(url, i+1)
	}
	req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	req.Header.Add("Cookie", "AD_RS_COOKIE=20081685; _gscu_1771678062=84559100mjln2j68; _trs_uv=hrhl_6_ixzw5q0o; _trs_ua_s_1=933x_6_ixzw5q0o")
	res, err := client.Do(req)
	if err != nil {
		Println("重试", err, i+1)
		return HttpGetI(url, i+1)
	}
	defer res.Body.Close()
	input, err := ioutil.ReadAll(res.Body)
	if err != nil {
		Println("重试", err, i+1)
		return HttpGetI(url, i+1)
	}
	//	if url == "http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2015/11/01/08/110108003.html" {
	//		Println(input)
	//		log.Fatal("kill")
	//	}
	out = []byte(dec.ConvertString(input))
	//	out = make([]byte, len(input))
	//	out = out[:]
	//	iconv.Convert(input, out, "gb2312", "utf-8")
	return out
}

func FUrl(url string) string {
	i := strings.LastIndex(url, "/")
	if i != -1 {
		url = url[0 : i+1]
	}
	return url
}

func LUrl(url string) string {
	i := strings.LastIndex(url, "/")
	if i != -1 {
		url = url[i-1:]
	}
	return url
}

//省
type Province struct {
	Pcode string `json:"pcode"`
	Name  string `json:"name"`
	Href  string `json:"-"`
	Code  string `json:"code"`
}

//市
type City struct {
	Pcode string `json:"pcode"`
	Name  string `json:"name"`
	Href  string `json:"-"`
	Code  string `json:"code"`
}

//县
type County struct {
	Pcode string `json:"pcode"`
	Name  string `json:"name"`
	Href  string `json:"-"`
	Code  string `json:"code"`
}

//镇
type Town struct {
	Pcode string `json:"pcode"`
	Name  string `json:"name"`
	Href  string `json:"-"`
	Code  string `json:"code"`
}

//村
type Village struct {
	Pcode    string `json:"pcode"`
	Name     string `json:"name"`
	Code     string `json:"code"`
	Classify string `json:"classify"`
}

func initAll() {
	gCurCookieJar, _ = cookiejar.New(nil)
}

func init() {
	errFile, err = os.OpenFile(dataError, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatalln("open file error !")
	}
	errLogger = log.New(errFile, "", log.LstdFlags)
	errLogger.SetFlags(errLogger.Flags() | log.LstdFlags)

	succFile, err = os.OpenFile(dataSuccess, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
	if err != nil {
		log.Fatalln("open file error !")
	}
}
